﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Rappelz.GameServer.Database;
using System.Data.Common;
using System.Data;

namespace Rappelz.GameServer
{
    public class GuildManager : BaseObject
    {
        const int MAX_GUILD_MEMBERS = 200;
        const int PERMISSION_SET_TYPE_COUNT = 6;
        const int DEFAULT_MAX_ALLIANCE_CNT = 3;

        public enum Permssion : int
        {
            None = 0,
            MemberLeast = 1,
            MemberMax = 6,
            Leader = 7,
        }

        public enum PermitRequiredAction : int
        {
            SetPermissionName = 0x1,
            MemberInvite = 0x2,
            MemberKick = 0x4,
            RevokePermission = 0x8,
            DungeonManagement = 0x10,
            RequestDungeonRaid = 0x20,
            AttackTeamCreate = 0x40,
            AttackTeamJoin = 0x80,
            Notice = 0x100,
            MemberMemo = 0x200,
            AllianceManagement = 0x400,
            AllianceJoin = 0x800,
            AllianceLeave = 0x1000,
            UpdateGuildIcon = 0x2000,
            AdvertiseManagement = 0x4000,
        }

        public enum AdvertiseType : int
        {
            None = 0,
            ListTypeOnly = 1,
            Normal = 2,
            Premium = 3,
        }

        public class GuildMemberTag
        {
            public bool bIsOnline;              // 0x0
            public int sid;                     // 0x4
            public int nLevel;                  // 0x8
            public int nJobId;                  // 0xc
            public byte nPermission;            // 0x10
            public string strMemo;              // 0x18
            public string strName = "";         // 0x8

            // Function       :     public void GuildManager::GuildMemberTag::GuildMemberTag(const struct GuildManager::GuildMemberTag &)

            
            public GuildMemberTag(int _sid, string szName, int lv, int job, byte permission, string memo)
            {
                this.bIsOnline = false;
                this.sid = _sid;
                this.strName = szName;
                this.nLevel = lv;
                this.nJobId = job;
                this.nPermission = permission;
                this.strMemo = memo;
            }
            
        }

        public class AllianceInfo
        {
            public int nAllianceID;                     // 0x0
            public int nLeadGuildID;                    // 0x4
            public string strAllianceName = "";         // 0x8
            public int nAlliancePassword;               // 0x24
            public int nMaxAllianceCnt;                 // 0x28
            public int nNameChanged;                    // 0x2C
            public List<GuildInfo> vGuildList = new List<GuildInfo>();  // 0x30
        }


        public class GuildInfo
        {
            public class RankInfo
            {
                public RankInfo(string _name, int _permission)
                {
                    name = _name;
                    permission = _permission;
                }
                public int permission;
                public string name;
            }

            public int nGuildPassword;                      // 0x0
            public int nGuildId;                            // 0x4
            public string strGuildName = "";                // 0x8
            public string strNotice = "";                   // 0x30
            public string strURL = "";                      // 0x58
            public int nLeaderSID;                          // 0x80
            public int nLeaderLevel;                        // 0x84
            public string strIconFileName = "";             // 0x88
            public int nIconSize;                           // 0xb0
            public string strBannerFileName = "";           // 0xb8
            public int nBannerSize;                         // 0xe0
            public AdvertiseType eAdvertiseType;            // 0xE4
            public long tAdvertiseEnd;                      // 0xE8
            public string strAdvertiseComment = "";         // 0xF0
            public bool bRecruiting;                        // 0x118
            public short nMinRecruitLevel;                  // 0x11A
            public short nMaxRecruitLevel;                  // 0x11C

            public int nNameChanged;                        // 0x120
            public int nDungeonId;                          // 0x124
            public long tDungeonBlockTime;                  // 0x128
            public long nGold;                              // 0x130
            public int nChaos;                              // 0x138
            public List<GuildMemberTag> vMemberNameList = new List<GuildMemberTag>();   // 0x140
            public List<uint> vOnlineList = new List<uint>();                           // 0x160
            public AllianceInfo pAllianceInfo;              // 0x180
            public long tAllianceBlockTime;                 // 0x188
            public int nDonationPoint;                      // 0x190
            public string[] aPermissionName = new string[PERMISSION_SET_TYPE_COUNT];    // 0x198
            public int[] aPermissionSet = new int[PERMISSION_SET_TYPE_COUNT];           // 0x288

// these aren't in 7.4 now....
            public RankInfo[] Ranks = new RankInfo[PERMISSION_SET_TYPE_COUNT];  // 0x198
            public int nRaidLeaderSID;                      // 0xC
            public string strLeaderName = "";               // 0x2C
            public string strRaidLeaderName = "";           // 0x48
            public int nRaidLeaderLevel;                    // 0x68



        }

        /// <summary>
        /// The instance!
        /// </summary>
        protected static GuildManager m_instance;

        /// <summary>
        /// Returns the instance
        /// </summary>
        public static GuildManager Instance
        {
            get
            {
                if (m_instance == null)
                    m_instance = new GuildManager();
                return m_instance;
            }
        }

// 
// UserDefinedType: GuildManager
// VTable         :   , Type:  *
// Enum           :   <unnamed-tag>, Type: int
// Data           :     constant 0xC8, Constant, Type: int, MAX_GUILD_MEMBER
// UserDefinedType:   GuildFunctor
// VTable         :     , Type:  *
// Function       :     public bool operator()(unsigned int)
// Function       :     public void GuildFunctor(const struct GuildManager::GuildFunctor &)
// Function       :     public void GuildFunctor()
// Function       :     public struct GuildManager::GuildFunctor & operator=(const struct GuildManager::GuildFunctor &)
// UserDefinedType:   GuildListFunctor
// VTable         :     , Type:  *
// Function       :     public bool operator()(int, const char *, const char *, int, const char *, int, int, int)
// Function       :     public void GuildListFunctor(const struct GuildManager::GuildListFunctor &)
// Function       :     public void GuildListFunctor()
// Function       :     public struct GuildManager::GuildListFunctor & operator=(const struct GuildManager::GuildListFunctor &)
// Function       :   public static class GuildManager & GuildManager::GetInstance()

        public bool Init()
        {
            this.m_nMaxGuildId = 0;
            this.m_nMaxAllianceId = 0;
            this.loadGuildMemberTagList();
            this.loadAllianceList();
            this.loadGuildList();
            this.finishLoading();
            return true;

        }
// Function       :   public bool GuildManager::DeInit()
// Function       :   public void GuildManager::ChangeGuildName(int, const char *, struct StructPlayer *)
// Function       :   public void GuildManager::ChangeGuildName(int, const char *)
// Function       :   public void GuildManager::onChangeGuildName(int, const char *, struct StructPlayer *)
// Function       :   public void GuildManager::SetGuildNameChanged(const int, const bool)

        public bool MakeGuild(string szGuildName, int nLeaderSID)
        {
            int nGuildId;

            lock(this.m_IntfLock)
            {
                if (this.getGuildInfo(szGuildName) == null)
                {
                    nGuildId = this.allocGuildId();
                    this.DBQuery(new DB_InsertGuild(szGuildName,nGuildId,nLeaderSID));
                    GuildInfo.RankInfo[] ranks = new GuildInfo.RankInfo[6];
                    ranks[0] = new GuildInfo.RankInfo("", 0);
                    ranks[1] = new GuildInfo.RankInfo("", 0);
                    ranks[2] = new GuildInfo.RankInfo("", 0);
                    ranks[3] = new GuildInfo.RankInfo("", 0);
                    ranks[4] = new GuildInfo.RankInfo("", 0);
                    ranks[5] = new GuildInfo.RankInfo("", 0);
                    this.makeGuild(nGuildId, szGuildName, nLeaderSID, 0, "", 0, 1, 0, 0, 0, 0, 0, 0, ranks);
                    return true;
                }
            }
            return false;
        }

        //public bool DestroyGuild(string const char *)
        public bool DestroyGuild(int nGuildId)
        {
            return false;
        }
// Function       :   public unsigned short GuildManager::IsDestroyableGuild(const int)
// Function       :   public bool GuildManager::SetRaidDungeonID(int, int)

        public int GetRaidDungeonID(int nGuildID)
        {
            return 0;
        }
// Function       :   public bool GuildManager::SetDungeonBlockTime(int, __int64)
// Function       :   public __int64 GuildManager::GetDungeonBlockTime(int)

        public int GetMemberCount(int nGuildID)
        {
            lock(this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildID);
                if (info != null)
                    return info.vMemberNameList.Count;
            }

            return 0;
        }
// Function       :   public int GuildManager::GetGuildID(const char *)
// Function       :   public bool SetGuildAllianceBlockTime(int, __int64)
// Function       :   public bool GuildManager::IsInGuildAllianceBlockTime(int)
// Function       :   public bool GuildManager::IsExistAlliance(const char *)
// Function       :   public bool GuildManager::CreateAlliance(int, const char *)
// Function       :   public void GuildManager::ChangeAllianceName(int, const char *, struct StructPlayer *)
// Function       :   public void GuildManager::onChangeAllianceName(int, const char *, struct StructPlayer *)
// Function       :   public void GuildManager::SetAllianceNameChanged(const int, const bool)
// Function       :   public bool GuildManager::AddToAlliance(int, int)
// Function       :   public bool GuildManager::LeaveAlliance(int)
        public int GetAllianceID(int nGuildID)
        {
            return 0;
        }

        public int GetAllianceLeaderGuildID(int nAllianceID)
        {
            return 0;
        }
// Function       :   public bool GuildManager::IsAllianceLeader(int, int)
// Function       :   public int GuildManager::GetAlliancePassword(int)
// Function       :   public int GuildManager::GetMaxAllianceCount(int)
// Function       :   public bool GuildManager::IncMaxAllianceCount(int)
// Function       :   public int GuildManager::GetAllianceMemberGuildCount(int)
// Function       :   public int GuildManager::GetAllianceMemberPlayerCount(int)
// Function       :   public bool GuildManager::DestroyAlliance(int)
// Function       :   public class std::basic_string<char,std::char_traits<char>,std::allocator<char> > GuildManager::GetAllianceName(int)
// Function       :   public class std::vector<int,std::allocator<int> > GuildManager::GetAllianceMemberID(int)
// Function       :   public void GuildManager::OnChangeCharacterName(int, const char *, const char *)

        public void OnChangeCharacterLevel(int nGuildID, string szName, int nLevel)
        {

        }
        public void OnChangeCharacterJob(int nGuildID, string szName, int nJobId)
        {

        }
// Function       :   public void GuildManager::LoadGuildInfo(int)

        public void GiveTax(int nGuildID, long nTax, int nChaos)
        {

        }
// Function       :   public const struct StructGold GuildManager::GetTaxAmount(int)
// Function       :   public int GuildManager::GetTaxChaosAmount(int)
// Function       :   public const struct StructGold GuildManager::DrawTax(int)
// Function       :   public int GuildManager::DrawTaxChaos(int, int)
// Function       :   public bool GuildManager::GetMemberInfo(int, const char *, struct GuildManager::GuildMemberTag *)
// Function       :   public int GuildManager::GetGuildPassword(const char *)
        public string GetGuildName(int nGuildId)
        {
            lock (this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildId);
                if (info != null)
                    return info.strGuildName;
            }
            return " ";
        }

        public string GetGuildIcon(int nGuildID)
        {
            lock (this.m_IntfLock)
            {
                GuildInfo info = getGuildInfo(nGuildID);
                if (info != null)
                    return info.strIconFileName;
            }
            return "";
        }

        public int GetGuildIconSize(int nGuildID)
        {
            lock(this.m_IntfLock)
            {
                GuildInfo info = getGuildInfo(nGuildID);
                if(info != null)
                    return info.nIconSize;
            }
            return 0;
        }
// Function       :   public bool IsLeader(const char *, const char *)

        public bool IsLeader(int nGuidId, string szPlayerName)
        {
            return false;
        }

        public bool IsRaidLeader(int nGuildID, string szPlayerName)
        {
            return false;
        }
// Function       :   public bool IsMember(int, const char *)
// Function       :   public unsigned short GuildManager::Promote(const int, const int)
// Function       :   public bool GuildManager::Promote(int, struct StructPlayer *)
// Function       :   public unsigned short GuildManager::AppointRaidLeader(int, struct StructPlayer *)
// Function       :   public unsigned short GuildManager::ClearRaidLeader(int)
// Function       :   public const bool IsValidRaidLeader(int)

        public int GetMaxLevel(int nGuildId)
        {
            int nResult = 0;
            lock (this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildId);
                if (info != null)
                {
                    nResult = 0;
                    foreach (uint id in info.vOnlineList)
                    {
                        Player p = Player.get(id) as Player;
                        if (p != null)
                        {
                            int l = p.GetLevel();
                            if (nResult < l)
                                nResult = l;
                        }
                    }
                }
                else
                {
                    nResult = 0;
                }
            }
            return nResult;
        }

        public int GetMinLevel(int nGuildId)
        {
            int nResult = 0;
            lock(this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildId);
                if (info != null)
                {
                    nResult = 999;
                    foreach (uint id in info.vOnlineList)
                    {
                        Player p = Player.get(id) as Player;
                        if (p != null)
                        {
                            int l = p.GetLevel();
                            if (nResult > l)
                                nResult = l;
                        }
                    }
                }
                else
                {
                    nResult = 0;
                }
            }
            return nResult;
        }
// Function       :   public int GetTotalLevel(int)
// Function       :   public const int GuildManager::GetLeaderSID(const int)
// Function       :   public const int GuildManager::GetRaidLeaderSID(const int)
        public string GetLeaderName(int nGuildID)
        {
            lock(this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildID);
                if (info != null)
                    return info.strLeaderName;
            }
            return " ";
        }

        public string GetRaidLeaderName(int nGuildID)
        {
            if (GameRule.bLimitDungeonEnterableLevel)
            {
                lock(this.m_IntfLock)
                {
                    GuildInfo info = this.getGuildInfo(nGuildID);
                    if (info != null)
                        return info.strRaidLeaderName;
                    else
                        return " ";

                }
            }
            return " ";
        }

// Function       :   public const int GuildManager::GetRaidLeaderLevel(int)

        public bool JoinGuild(string szGuildName, Player pPlayer)
        {
            lock(this.m_IntfLock)
            {
                return this.joinGuild(this.getGuildInfo(szGuildName), pPlayer);
            }
            return false;
        }

// Function       :   public bool GuildManager::JoinGuild(int, struct StructPlayer *)
// Function       :   public bool GuildManager::LeaveGuild(const char *, const char *)

        public bool LeaveGuild(int nGuildId, string szPlayerName)
        {
            return false;
        }
//        public bool onLogin(string onst char *, struct StructPlayer *)
        public bool onLogin(int nGuildID, Player player)
        {
            lock(this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildID);
                if (info != null)
                {
                    return this.signAsOnLine(info, player);
                }
                else
                {
                    player.m_nGuildId = 0;
                }

            }
            return false;
        }
// Function       :   public bool onLogout(const char *, struct StructPlayer *)

        public bool onLogout(int nGuildId, Player pPlayer)
        {
            lock (this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildId);
                if (info != null)
                {
                    return this.signAsOffLine(info, pPlayer);
                }
            }
            return false;
        }
// Function       :   public unsigned int GuildManager::DoEachGuild(struct GuildManager::GuildListFunctor &)
// Function       :   public unsigned int GuildManager::DoEachAllianceGuild(int, struct GuildManager::GuildListFunctor &)

        public uint DoEachMember(int nGuildID, GuildFunctor fn)
        {
            uint r = 0;

            lock(this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildID);
                if (info != null)
                    r = this.doEachMember(info, fn);
            }
            return r;
        }

        public uint DoEachMember(string szGuildName, GuildFunctor fn)
        {
            uint r = 0;

            lock (this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(szGuildName);
                if (info != null)
                    r = this.doEachMember(info, fn);
            }
            return r;
        }

        public void GetNearMember(Player pPtr, float distance, List<Player> vList)
        {

        }

        public void GetOfflineMember(int nGuildID, List<GuildMemberTag> vList)
        {
            lock(this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(nGuildID);
                if (info != null)
                {
                    foreach (GuildMemberTag mt in info.vMemberNameList)
                    {
                        if(!mt.bIsOnline)
                            vList.Add(mt);
                    }
                }
            }
        }


        public bool IsExistGuild(string szGuildName)
        {
            return getGuildInfo(szGuildName) != null;

        }
// Function       :   public bool GuildManager::AddGuildDonationPoint(const int, const int)
// Function       :   public void GuildManager::Push(struct GameDBManager::DBProc *)
// Function       :   public void GuildManager::onEndQuery()
// Function       :   public void GuildManager(const class GuildManager &)
// Function       :   public void GuildManager::GuildManager()
// Function       :   public void GuildManager::~GuildManager()

        protected void loadAllianceList()
        {
            DbConnection conn = GameDBManager.Instance.CreateConnection();
            DbCommand cmd = conn.CreateCommand();

            cmd.CommandText = "select * from Alliance";
            cmd.CommandType = CommandType.Text;

            conn.Open();
            int count = 0;
            try
            {
                DbDataReader dr = cmd.ExecuteReader();
                while (dr.Read())
                {
                    int off = 0;

                    int sid = dr.GetInt32(off++);
                    string name = dr.GetString(off++);
                    int lead_guild_id = dr.GetInt32(off++);
                    int max_alliance_cnt = dr.GetInt32(off++);
                    int name_changed = dr.GetInt32(off++);
                    if (this.m_nMaxAllianceId < sid)
                        this.m_nMaxAllianceId = sid;

                    this.makeAlliance(sid,lead_guild_id,name,max_alliance_cnt,name_changed);
                    count++;
                }
            }
            catch (Exception ex)
            {
                Globals.Log.Error("GuildManager.loadAllianceList Exception: {0}", ex);
            }
            conn.Close();

            Globals.Log.Info("Total {0} Alliances loaded...", count);
        }

        protected void loadGuildMemberTagList()
        {
            List<GuildMemberTag> ptagList = null;
            DbConnection conn = GameDBManager.Instance.CreateConnection();
            DbCommand cmd = conn.CreateCommand();

            cmd.CommandText = "smp_read_guild_member_list";
            cmd.CommandType = CommandType.StoredProcedure;

            conn.Open();
            int count = 0;
            try
            {
                DbDataReader dr = cmd.ExecuteReader();
                int currentGuildId = 0;
                while (dr.Read())
                {
                    int off = 0;

//SELECT M.player_id, M.guild_id, M.permission, M.memo, C.name, C.lv, C.job FROM dbo.Character C WITH (NOLOCK) INNER JOIN dbo.GuildMember M WITH (NOLOCK) ON C.sid = M.player_id AND M.guild_id > 0 AND C.name NOT LIKE N'@%%' ORDER BY M.guild_id, M.permission desc, M.player_id
                    int sid = dr.GetInt32(off++);
                    int guild_id = dr.GetInt32(off++);
                    byte rank = dr.GetByte(off++);
                    string memo = dr.GetString(off++);
                    string name = dr.GetString(off++);
                    int lv = dr.GetInt32(off++);
                    int job = dr.GetInt32(off++);

                    if(currentGuildId == 0 || currentGuildId != guild_id)
                    {
                        if(!this.m_hshGuildMemberTagList.ContainsKey(guild_id))
                        {
                            this.m_hshGuildMemberTagList.Add(guild_id, new List<GuildMemberTag>());
                        }
                        ptagList = this.m_hshGuildMemberTagList[guild_id];

                        currentGuildId = guild_id;
                    }
                    GuildMemberTag mt = new GuildMemberTag(sid, name, lv, job,rank,memo);
                    ptagList.Add(mt);
                    count++;
                }
            }
            catch (Exception ex)
            {
                Globals.Log.Error("GuildManager.loadAllianceList Exception: {0}", ex);
            }
            conn.Close();

            Globals.Log.Info("Total {0} GuildMemberTags Loaded...", count);
        }

        protected GuildMemberTag _getGuildMemberTagList(int guild_id, int leader_sid, ref List<GuildMemberTag> result)
        {
            GuildMemberTag r = null;

            if(this.m_hshGuildMemberTagList.ContainsKey(guild_id))
            {
                result = this.m_hshGuildMemberTagList[guild_id];
                foreach(GuildMemberTag mt in this.m_hshGuildMemberTagList[guild_id])
                {
                    if (mt.sid == leader_sid)
                    {
                        r = mt;
                        break;
                    }
                }
                this.m_hshGuildMemberTagList.Remove(guild_id);
            }
            else
            {
                Globals.Log.Error("Guild info with no member detected: guild_id({0})", guild_id);
            }
            return r;
        }

        protected GuildMemberTag getUserTagInGuild(int guild_id, int user_sid)
        {
            lock(this.m_IntfLock)
            {
                GuildInfo info = this.getGuildInfo(guild_id);
                if (info != null)
                {
                    foreach (GuildMemberTag mt in info.vMemberNameList)
                    {
                        if(mt.sid == user_sid)
                            return mt;
                    }
                }

            }
            return null;
        }

        protected void loadGuildList()
        {
            DbConnection conn = GameDBManager.Instance.CreateConnection();
            DbCommand cmd = conn.CreateCommand();

            cmd.CommandText = "select * from Guild";
            cmd.CommandType = CommandType.Text;

            conn.Open();
            int count = 0;
            try
            {
                DbDataReader dr = cmd.ExecuteReader();
                while (dr.Read())
                {
                    int off = 0;

                    int sid = dr.GetInt32(off++);
                    string name = dr.GetString(off++);
                    int leader_id = dr.GetInt32(off++);
                    int raid_leader_id = dr.GetInt32(off++);
                    string notice = dr.GetString(off++);
                    string icon = dr.GetString(off++);
                    int icon_size = dr.GetInt32(off++);
                    int name_changed = dr.GetInt32(off++);
                    int dungeon_id = dr.GetInt32(off++);
                    long dungeon_block_time = dr.GetInt64(off++);
                    long gold = dr.GetInt64(off++);
                    int chaos = dr.GetInt32(off++);
                    int alliance_id = dr.GetInt32(off++);
                    long alliance_block_time = dr.GetInt64(off++);
                    int donation_point = dr.GetInt32(off++);
                    string website = dr.GetString(off++);
                    string rank1Name = dr.GetString(off++);
                    string rank2Name = dr.GetString(off++);
                    string rank3Name = dr.GetString(off++);
                    string rank4Name = dr.GetString(off++);
                    string rank5Name = dr.GetString(off++);
                    string rank6Name = dr.GetString(off++);
                    int rank1p = dr.GetInt32(off++);
                    int rank2p = dr.GetInt32(off++);
                    int rank3p = dr.GetInt32(off++);
                    int rank4p = dr.GetInt32(off++);
                    int rank5p = dr.GetInt32(off++);
                    int rank6p = dr.GetInt32(off++);
                    if (this.m_nMaxGuildId < sid)
                        this.m_nMaxGuildId = sid;

                    GuildInfo.RankInfo[] ranks = new GuildInfo.RankInfo[6];
                    ranks[0] = new GuildInfo.RankInfo(rank1Name, rank1p);
                    ranks[1] = new GuildInfo.RankInfo(rank2Name, rank2p);
                    ranks[2] = new GuildInfo.RankInfo(rank3Name, rank3p);
                    ranks[3] = new GuildInfo.RankInfo(rank4Name, rank4p);
                    ranks[4] = new GuildInfo.RankInfo(rank5Name, rank5p);
                    ranks[5] = new GuildInfo.RankInfo(rank6Name, rank6p);

                    GuildInfo guild = this.makeGuild(sid, name, leader_id, raid_leader_id, icon,icon_size,name_changed,dungeon_id,dungeon_block_time,gold,chaos,alliance_block_time,donation_point,ranks);
                    guild.strNotice = notice;
                    guild.strURL = website;

                    bool bLeaderFound = false;

                    GuildMemberTag leaderTag = GuildManager.Instance._getGuildMemberTagList(sid,leader_id, ref guild.vMemberNameList);
                    
                    if (guild.vMemberNameList.Count > 0)
                    {
                        if (leaderTag == null)
                        {
                            guild.nLeaderSID = guild.vMemberNameList[0].sid;
                            leaderTag =guild.vMemberNameList[0];
                            bLeaderFound = true;
                        }
                        guild.strLeaderName = leaderTag.strName;
                        guild.nLeaderLevel = leaderTag.nLevel;
                        if (guild.nRaidLeaderSID != 0)
                        {
                            GuildMemberTag leaderRaid = this.getUserTagInGuild(guild.nGuildId, guild.nRaidLeaderSID);
                            if (leaderRaid == null)
                            {
                                guild.nRaidLeaderSID = 0;
                                bLeaderFound = true;
                            }
                            else
                            {
                                guild.strRaidLeaderName = leaderRaid.strName;
                                guild.nRaidLeaderLevel = leaderRaid.nLevel;
                            }
                        }
                        if (alliance_id != 0)
                        {
                            AllianceInfo alliance = this.getAllianceInfo(alliance_id);
                            if (alliance != null)
                            {
                                alliance.vGuildList.Add(guild);
                            }
                            else
                            {
                                this.DBQuery(new DB_SetGuildAllianceID(sid, 0));
                            }
                            guild.pAllianceInfo = alliance;
                        }
                        if (bLeaderFound)
                        {
                            this.DBQuery(new DB_UpdateGuildInfo(guild.nGuildId,guild.nLeaderSID,guild.nRaidLeaderSID,guild.nDungeonId));
                        }
                    }
                    else
                    {
                        this.DestroyGuild(guild.nGuildId);
                    }
                    count++;
                }

/*
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    (std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > *)&_Where,
                    (unsigned int *)v1->m_vAllianceList._Myfirst,
                    &v1->m_vAllianceList.baseclass_0.___u0.baseclass_0);
                v27 = (unsigned int *)v1->m_vAllianceList._Mylast;
                for ( szGuildName[11] = (_variant_t *)&v1->m_vAllianceList; ; szGuildName[11] = (_variant_t *)&v1->m_vAllianceList )
                {
                    std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                        (std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > *)&gold,
                        v27,
                        (std::_Container_base *)szGuildName[11]);
                    if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                             (std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&_Where,
                             (std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&gold) )
                        break;
                    v28 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                    if ( std::vector<KHash<RankingManager::_RANKING_DATA___khash_def::hashPr_mod_basic<int>>::node___std::allocator<KHash<RankingManager::_RANKING_DATA___khash_def::hashPr_mod_basic<int>>::node__>>::size((std::vector<unsigned int,std::allocator<unsigned int> > *)(LODWORD(v28->end.x) + 48)) )
                    {
                        bLeaderFound = 0;
                        v32 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                        std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                            (std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > *)&itGuild,
                            *(unsigned int **)(LODWORD(v32->end.x) + 52),
                            (std::_Container_base *)(LODWORD(v32->end.x) + 48));
                        v33 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                        std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                            (std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > *)&_Right,
                            *(unsigned int **)(LODWORD(v33->end.x) + 56),
                            (std::_Container_base *)(LODWORD(v33->end.x) + 48));
                        if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                                 (std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&itGuild,
                                 &_Right) )
                            goto LABEL_63;
                        do
                        {
                            v34 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                            if ( *(_DWORD *)(LODWORD(v34->end.x) + 4) == *(_DWORD *)(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&itGuild)->end.x)
                                                                                   + 4) )
                                bLeaderFound = 1;
                            std::_Vector_const_iterator<AutoAuctionInfo___std::allocator<AutoAuctionInfo__>>::operator__((std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&itGuild);
                            v35 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                            std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                                (std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > *)&_Right,
                                *(unsigned int **)(LODWORD(v35->end.x) + 56),
                                (std::_Container_base *)(LODWORD(v35->end.x) + 48));
                        }
                        while ( !std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                                     (std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&itGuild,
                                     &_Right) );
                        if ( !bLeaderFound )
                        {
            LABEL_63:
                            v36 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                            std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                                (std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > *)&v58,
                                *(unsigned int **)(LODWORD(v36->end.x) + 52),
                                (std::_Container_base *)(LODWORD(v36->end.x) + 48));
                            while ( 1 )
                            {
                                v38 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                                    (std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > *)&v52,
                                    *(unsigned int **)(LODWORD(v38->end.x) + 56),
                                    (std::_Container_base *)(LODWORD(v38->end.x) + 48));
                                if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                                         (std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&v58,
                                         &v52) )
                                    break;
                                pInfo = (DB_SetGuildAllianceID *)GameDBManager::DBProc::operator new(0x168u);
                                LOBYTE(v64) = 7;
                                if ( pInfo )
                                {
                                    v37 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&v58)->end.x;
                                    szGuildName[11] = 0;
                                    szGuildName[10] = *(_variant_t **)(LODWORD(v37) + 4);
                                    DB_SetGuildAllianceID::DB_SetGuildAllianceID(pInfo, (int)szGuildName[10], 0);
                                }
                                else
                                {
                                    LODWORD(v37) = 0;
                                }
                                LOBYTE(v64) = 1;
                                GuildManager::Push(v1, LODWORD(v37));
                                *(_DWORD *)(LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&v58)->end.x)
                                          + 204) = 0;
                                std::_Vector_const_iterator<AutoAuctionInfo___std::allocator<AutoAuctionInfo__>>::operator__((std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&v58);
                            }
                            pInfo = (DB_SetGuildAllianceID *)GameDBManager::DBProc::operator new(0x164u);
                            LOBYTE(v64) = 8;
                            if ( pInfo )
                            {
                                szGuildName[11] = (_variant_t *)*LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where)->end.x);
                                DB_DeleteAllianceInfo::DB_DeleteAllianceInfo((DB_DeleteAllianceInfo *)pInfo, (int)szGuildName[11]);
                            }
                            else
                            {
                                v39 = 0;
                            }
                            LOBYTE(v64) = 1;
                            GuildManager::Push(v1, v39);
                            v40 = (GuildManager::AllianceInfo **)std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                            v41 = *v40;
                            if ( *v40 )
                            {
                                GuildManager::AllianceInfo::_AllianceInfo(*v40);
                                operator delete(v41);
                            }
                            std::vector<StructPet___std::allocator<StructPet__>>::erase(
                                (std::vector<StructSkill *,std::allocator<StructSkill *> > *)&v1->m_vAllianceList,
                                (std::_Vector_iterator<StructSkill *,std::allocator<StructSkill *> > *)&Source.baseclass_0.___u0._s0.llVal,
                                _Where);
                        }
                        std::_Vector_const_iterator<AutoAuctionInfo___std::allocator<AutoAuctionInfo__>>::operator__((std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > *)&_Where);
                    }
                    else
                    {
                        pInfo = (DB_SetGuildAllianceID *)GameDBManager::DBProc::operator new(0x164u);
                        LOBYTE(v64) = 6;
                        if ( pInfo )
                        {
                            szGuildName[11] = (_variant_t *)*LODWORD(std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where)->end.x);
                            DB_DeleteAllianceInfo::DB_DeleteAllianceInfo((DB_DeleteAllianceInfo *)pInfo, (int)szGuildName[11]);
                        }
                        else
                        {
                            v29 = 0;
                        }
                        LOBYTE(v64) = 1;
                        GuildManager::Push(v1, v29);
                        v30 = (GuildManager::AllianceInfo **)std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_((std::_Vector_const_iterator<ArMoveVector::MOVE_INFO,std::allocator<ArMoveVector::MOVE_INFO> > *)&_Where);
                        v31 = *v30;
                        if ( *v30 )
                        {
                            GuildManager::AllianceInfo::_AllianceInfo(*v30);
                            operator delete(v31);
                        }
                        std::vector<StructPet___std::allocator<StructPet__>>::erase(
                            (std::vector<StructSkill *,std::allocator<StructSkill *> > *)&v1->m_vAllianceList,
                            (std::_Vector_iterator<StructSkill *,std::allocator<StructSkill *> > *)&thisa.baseclass_0.___u0._s0.llVal,
                            _Where);
                    }
                    v27 = (unsigned int *)v1->m_vAllianceList._Mylast;
                }
*/
            }
            catch (Exception ex)
            {
                Globals.Log.Error("GuildManager.loadAllianceList Exception: {0}", ex);
            }
            conn.Close();

            Globals.Log.Info("Total {0} Alliances loaded...", count);
        }

        protected void finishLoading()
        {

        }
// Function       :   protected bool GuildManager::updateGuildInfo(int, const char *, int)
// Function       :   protected const unsigned short GuildManager::_setRaidLeader(const int, const int, const int, const char *)
// Enum           :   <unnamed-tag>, Type: int
// Data           :     constant 0x3, Constant, Type: int, DEFAULT_MAX_ALLIANCE_CNT

        protected AllianceInfo makeAlliance(int nAllianceId, int nLeadGuildId, string szName, int nMaxAllianceCnt, int nNameChaned)
        {
            AllianceInfo info = new AllianceInfo();

            info.nAllianceID = nAllianceId;
            info.nAlliancePassword = Globals.GetRandomInt32();
            info.nLeadGuildID =nLeadGuildId;
            info.strAllianceName = szName;
            info.nMaxAllianceCnt = nMaxAllianceCnt;
            info.nNameChanged = nNameChaned;
            this.m_vAllianceList.Add(info);
            return info;
        }

// Function       :   protected struct GuildManager::AllianceInfo * GuildManager::getAllianceInfo(const char *)

        protected AllianceInfo getAllianceInfo(int nAllianceId)
        {
            foreach (AllianceInfo ai in this.m_vAllianceList)
            {
                if(ai.nAllianceID == nAllianceId)
                    return ai;
            }
            return null;
        }
// Function       :   protected unsigned short GuildManager::isDestroyableGuild(struct GuildManager::GuildInfo *)
// Function       :   protected bool GuildManager::leaveGuild(struct GuildManager::GuildInfo *, const char *)

        protected bool joinGuild(GuildInfo info, Player pPlayer)
        {
            if (info != null && pPlayer != null)
            {
                GuildMemberTag mt = new GuildMemberTag(pPlayer.m_nUID, pPlayer.GetName(),pPlayer.GetLevel(),pPlayer.GetJobId(),1,"");
                info.vMemberNameList.Add(mt);

                GuildManager.Instance.signAsOnLine(info, pPlayer);
                pPlayer.m_nGuildId = info.nGuildId;
                pPlayer.m_nPrevGuildId = 0;
                pPlayer.m_nGuildRank = 1;
                pPlayer.m_strGuildMemo = "";
                this.DBQuery(new DB_SetGuild(pPlayer.m_nUID,info.nGuildId,0,1,""));
                return true;
            }
            return false;

        }

        // Function       :   protected bool GuildManager::destroyGuild(struct GuildManager::GuildInfo *)

        protected GuildInfo makeGuild(int nGuildID, string szGuildName, int nLeaderSID, int nRaidLeaderSID, string szGuildIconName, int nGuildIconSize, int name_changed, int dungeon_id, long dungeon_block_time, long gold, int chaos, long alliance_block_time, int donation_point, GuildInfo.RankInfo[] rankInfo)
        {
            GuildInfo info = new GuildInfo();
            info.strGuildName = szGuildName;
            info.nGuildId = nGuildID;
            info.nGuildPassword = Globals.GetRandomInt32();
            info.nLeaderSID = nLeaderSID;
            info.nRaidLeaderSID = nRaidLeaderSID;
            info.strIconFileName = szGuildIconName;
            info.nIconSize = nGuildIconSize;
            info.nNameChanged = name_changed;
            info.nDungeonId = dungeon_id;
            info.tDungeonBlockTime = dungeon_block_time;
            info.nGold = gold;
            info.nChaos = chaos;
            info.pAllianceInfo = null;
            info.tAllianceBlockTime = alliance_block_time;
            info.nDonationPoint = donation_point;
            this.m_hshGuildName.Add(szGuildName,info);
            this.m_hshGuildID.Add(nGuildID,info);
            this.m_vGuildList.Add(info);
            info.Ranks[0] = rankInfo[0];
            info.Ranks[1] = rankInfo[1];
            info.Ranks[2] = rankInfo[2];
            info.Ranks[3] = rankInfo[3];
            info.Ranks[4] = rankInfo[4];
            info.Ranks[5] = rankInfo[5];
            return info;
        }

        protected int allocGuildId()
        {
            Interlocked.Increment(ref this.m_nMaxGuildId);
            return this.m_nMaxGuildId;
        }
// Function       :   protected int GuildManager::allocAllianceId()

        public GuildInfo getGuildInfo(int nGuildId)
        {
            if (this.m_hshGuildID.ContainsKey(nGuildId))
                return this.m_hshGuildID[nGuildId];
            return null;
        }

        protected GuildInfo getGuildInfo(string szGuildName)
        {
            if(this.m_hshGuildName.ContainsKey(szGuildName))
                return this.m_hshGuildName[szGuildName];
            return null;
        }

        protected uint doEachMember(GuildInfo info, GuildFunctor fn)
        {
            uint r = 0;
            foreach (uint h in info.vOnlineList)
            {
                fn.run(h);
                r++;
            }
            return r;
        }

        protected bool signAsOnLine(GuildInfo info, Player player)
        {
            if (info != null)
            {
                info.vOnlineList.Add(player.m_hHandle);

                if (info.nLeaderSID == player.m_nUID)
                {
                    info.strLeaderName = player.GetName();
                    info.nLeaderLevel = player.GetLevel();
                }
                else if (info.nRaidLeaderSID == player.m_nUID)
                {
                    info.strRaidLeaderName = player.GetName();
                    info.nRaidLeaderLevel = player.GetLevel();
                }
                foreach (GuildMemberTag mt in info.vMemberNameList)
                {
                    if (mt.sid == player.m_nUID)
                    {
                        mt.bIsOnline = true;
                        return true;
                    }
                }
                return true;
            }
            return false;

        }

        protected bool signAsOffLine(GuildInfo info, Player player)
        {
            if (info != null)
            {
                for(int i = info.vOnlineList.Count-1; i >= 0; --i)
                {
                    if(info.vOnlineList[i] == player.m_hHandle)
                    {
                        info.vOnlineList.RemoveAt(i);
                        break;
                    }
                }

                foreach (GuildMemberTag mt in info.vMemberNameList)
                {
                    if ( mt.sid == player.m_nUID)
                    {
                        mt.bIsOnline = false;
                        return false;
                    }
                }
            }
            return false;
        }

        public int m_nMaxGuildId;                               // 0x4
        public int m_nMaxAllianceId;                            // 0x8
        private object m_IntfLock = new object();
// Data           :   this+0xC, Member, Type: class XCriticalSection, m_QueryLock
// Data           :   this+0x4C, Member, Type: class XCriticalSection, 

        public Dictionary<string, GuildInfo> m_hshGuildName = new Dictionary<string, GuildInfo>();  // 0x8C
        public Dictionary<int, GuildInfo> m_hshGuildID = new Dictionary<int, GuildInfo>();          // 0xA8
        public Dictionary<int, List<GuildMemberTag>> m_hshGuildMemberTagList = new Dictionary<int, List<GuildMemberTag>>(); // 0xC4
        public List<GuildInfo> m_vGuildList = new List<GuildInfo>();                                // 0xE0
        public List<AllianceInfo> m_vAllianceList = new List<AllianceInfo>();                       // 0xF0

    }
}
